﻿Imports System.Runtime.Serialization
Imports System.IO

''' <summary>
''' Central class for dealing with scripts.  
''' </summary>
''' <remarks></remarks>
''' <editHistory></editHistory>
<DataContract(Namespace:=Constants.DataContractNamespace)> _
Public Class ScriptProject
    Inherits ItemBase

    'Private _name As String
    Private _scriptGroups As ScriptGroups

    ''' <summary>
    ''' Creates a new instance of the ScriptProject class.
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        _scriptGroups = New ScriptGroups
    End Sub

    ''' <summary>
    ''' Gets a value indicating whether the script project is dirty.
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    Public Overrides ReadOnly Property IsDirty() As Boolean
        Get
            If Me.Options IsNot Nothing AndAlso Me.Options.IsDirty Then
                Return True
            ElseIf Me.ScriptGroups.IsDirty Then
                Return True
            Else
                Return MyBase.IsDirty
            End If
        End Get
    End Property

    ''' <summary>
    ''' Marks the object as clean
    ''' </summary>
    ''' <remarks></remarks>
    Friend Overrides Sub MarkClean()
        MyBase.MarkClean()

        Me.ScriptGroups.MarkClean()

        If Me.Options IsNot Nothing Then
            Me.Options.MarkClean()
        End If
    End Sub

    '''' <summary>
    '''' Gets or sets the name of the script project
    '''' </summary>
    '''' <value></value>
    '''' <remarks></remarks>
    '<DataMember()> _
    'Public Property Name() As String
    '    Get
    '        Return _name
    '    End Get
    '    Set(ByVal value As String)
    '        _name = value

    '        MarkDirty("Name")
    '    End Set
    'End Property

    ''' <summary>
    ''' Gets the script groups for this project
    ''' </summary>
    ''' <value></value>
    ''' <remarks></remarks>
    <DataMember()> _
    Public Property ScriptGroups() As ScriptGroups
        Get
            Return _scriptGroups
        End Get
        Private Set(ByVal value As ScriptGroups)
            _scriptGroups = value
        End Set
    End Property

    Private _options As ScriptProjectOptions

    <DataMember()> _
    Public Property Options() As ScriptProjectOptions
        Get
            Return _options
        End Get
        Set(ByVal value As ScriptProjectOptions)
            If _options IsNot value Then
                _options = value

                MarkDirty("Options")
            End If
        End Set
    End Property

    ''' <summary>
    ''' Saves the project
    ''' </summary>
    ''' <param name="filename"></param>
    ''' <remarks></remarks>
    Public Sub Save(ByVal filename As String)

        Try

            'Create the serializer
            Dim serializer As New DataContractSerializer(GetType(ScriptProject))

            'Create a temp stream
            Using stream As New MemoryStream

                'Write the object
                serializer.WriteObject(stream, Me)

                'Write out the contents
                File.WriteAllBytes(filename, stream.ToArray())

                'Mark me clean!
                Me.MarkClean()

            End Using

        Catch
            Throw
        Finally

            'We want to make sure the options get saved, even if the main file can't be.
            SaveOptions(filename)
        End Try

    End Sub

    ''' <summary>
    ''' Saves the options
    ''' </summary>
    ''' <param name="filename">This is the path to the main file, not the options file.</param>
    ''' <remarks></remarks>
    Public Sub SaveOptions(ByVal filename As String)

        'Consider the options
        If Me.Options IsNot Nothing Then

            'Get the path for the options
            Dim optionsPath As String = GetOptionsFilePath(filename)

            'Create the serializer
            Dim optionsSerializer As New DataContractSerializer(GetType(ScriptProjectOptions))

            'Use a memory stream for this
            Using optionsStream As New MemoryStream

                'Serialize the object
                optionsSerializer.WriteObject(optionsStream, Me.Options)

                'Write out the options
                File.WriteAllBytes(optionsPath, optionsStream.ToArray())

            End Using

            'Mark it clean
            Me.Options.MarkClean()

        End If


    End Sub

    ''' <summary>
    ''' Gets the path to the options file for a given filename.
    ''' </summary>
    ''' <param name="mainFilename">This is the filename of the project (not the options file).</param>
    ''' <returns></returns>
    Private Shared Function GetOptionsFilePath(ByVal mainFilename As String) As String

        'TODO: I think that we can make this a little more simple by getting the full path without the 
        ' extension instead of putting these all together like this.
        Return Path.Combine(Path.GetDirectoryName(mainFilename), Path.GetFileNameWithoutExtension(mainFilename) & Constants.OptionsFileExtension)

    End Function

    ''' <summary>
    ''' Opens the specified project
    ''' </summary>
    ''' <param name="filename"></param>
    ''' <returns></returns>
    Public Shared Function Open(ByVal filename As String) As ScriptProject

        'Create the serializer
        Dim serializer As New DataContractSerializer(GetType(ScriptProject))

        'Get the data from the file
        Dim data() As Byte = File.ReadAllBytes(filename)

        'Create a stream to deal with the data
        Using Stream As New MemoryStream(data)

            'Return the deserialized object
            Dim project As ScriptProject = DirectCast(serializer.ReadObject(Stream), ScriptProject)

            'mark it clean
            project.MarkClean()

            'Now, get the options
            Try

                'Get the path to the options
                Dim optionsPath As String = GetOptionsFilePath(filename)

                'get the data
                Dim optionsData() As Byte = File.ReadAllBytes(optionsPath)

                'Create the serializer
                Dim optionsSerializer As New DataContractSerializer(GetType(ScriptProjectOptions))

                'We'll use a stream to perform this operation.
                Using optionsStream As New MemoryStream(optionsData)

                    'Get the options
                    Dim options As ScriptProjectOptions = DirectCast(optionsSerializer.ReadObject(optionsStream), ScriptProjectOptions)

                    'Attach the options to the file
                    project.Options = options

                    options.MarkClean()

                End Using

                'Mark the project as clean
                project.MarkClean()

            Catch ex As FileNotFoundException

                'This is ok.  In this case, just create a new options object.
                project.Options = New ScriptProjectOptions
            End Try



            'Return it!
            Return project

        End Using

    End Function

End Class
